#include "NetBase.h"

using namespace Hiranipra;
using namespace Hiranipra::Net;
//using namespace Hiranipra::Platform;

class EnetInitializer
{
public:
	EnetInitializer()
	{
		enet_initialize();
	}
	~EnetInitializer()
	{
		enet_deinitialize();
	}
};
static EnetInitializer _enetInitializer;

NetBase::NetBase()
{
}

NetBase::~NetBase()
{
	if( _selfHost != NULL )
		enet_host_destroy( _selfHost );
	_selfHost = NULL;
}

void NetBase::SetBandwidthLimits( uint32 incomingBandwidth, uint32 outgoingBandwidth )
{
	enet_host_bandwidth_limit( _selfHost, incomingBandwidth, outgoingBandwidth );
}

bool NetBase::Poll( uint32 timeout )
{
	ENetEvent enetEvent;
	int result = enet_host_service( _selfHost, &enetEvent, timeout );
	//  0 = no event
	// >0 = event
	// <0 = failure
	if( result > 0 )
	{
		NetEvent::NetEventName name;
		switch( enetEvent.type )
		{
		case ENET_EVENT_TYPE_NONE:			return false;
		case ENET_EVENT_TYPE_CONNECT:		name = NetEvent::Connected;		this->OnConnect( enetEvent );		break;
		case ENET_EVENT_TYPE_DISCONNECT:	name = NetEvent::Disconnected;	this->OnDisconnect( enetEvent );	break;
		case ENET_EVENT_TYPE_RECEIVE:		name = NetEvent::Received;											break;
		}
		Peer* peer = ( enetEvent.peer != NULL ) ? ( Peer* )enetEvent.peer->data : NULL;
		Packet packet( enetEvent.packet );
		NetEvent ev( name, peer, enetEvent.channelID, enetEvent.data, &packet );
		this->EventSource.Fire( ev );
		if( enetEvent.packet != NULL )
			enet_packet_destroy( enetEvent.packet );
		return true;
	}
	else
		return false;
}

void NetBase::Flush()
{
	enet_host_flush( _selfHost );
}

Packet* NetBase::AllocatePacket( PacketFlags flags, uint32 size )
{
	ENetPacket* enetPacket = enet_packet_create( NULL, size, flags );
	Packet* packet = new Packet( enetPacket );
	return packet;
}
